﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using Warensoft.Utility;
using Warensoft.Socket;
using Warensoft.Socket.EventArgs;
using System.IO;
using Warensoft.Socket.Extension;
using Warensoft.Socket.MessageDataStructs;
using System.Diagnostics;
namespace Warensoft.Socket
{
    public class ClientSocket:IDisposable 
    {
        /// <summary>
        /// 所处的服务器的引用
        /// </summary>
        internal SocketServer Server { get; set; }

        public string Name { get; set; }
        byte[] buffer = new byte[0];
        private System.Net .Sockets.Socket clientSocket = null;
        /// <summary>
        /// 当有新消息时触发
        /// </summary>
        public event EventHandler<NewMessageEventArgs> NewMessage;
        public event EventHandler<NewMessageEventArgs> MessageSent;
        public event EventHandler<ErrorEventArgs> OnError;
        public event EventHandler <DisconnectedEventArgs >Disconnected;
        private bool triggerDisconnected = true;
       
        private bool disconnected = false;
        public bool SocketDisconnected { get { return this.disconnected; } }
        public ClientSocket(System.Net.Sockets .Socket socket)
        {
            this.clientSocket = socket;
        }

        protected void DispatchNewMessages(Message message)
        {
            foreach (var msg in message .Packages )
            {
                if (this.NewMessage !=null)
                {
                    this.NewMessage(this, new NewMessageEventArgs() { MessageStream = msg });
                }
            }
        }

        public void SendMessage(PackageBase message)
        {
            this.SendMessage(message.ToArray ());
        }
        public void SendMessage(Message message)
        {
            this.SendMessage(message.ToBytes());
        }
        public void SendMessage(byte[] buffer)
        {
            if (this.disconnected)
            {
                return;
            }

            byte[] msgArray = buffer;
            //注意这里一定要用Socket的异步发送
            try
            {
                if (this.clientSocket.Connected == true)
                {

                    this.clientSocket.BeginSend(msgArray, 0, msgArray.Length, SocketFlags.None, result =>
                    {
                      
                        if (this.clientSocket.Connected == true)
                        {
                            try
                            {

                                this.clientSocket.EndSend(result);
                                if (this.MessageSent != null)
                                {
                                    MemoryStream message = new MemoryStream(buffer );
                                    this.MessageSent(this, new NewMessageEventArgs() { MessageStream = message });
                                }
                            }
                            catch (SocketException ex)
                            {
                                this.disconnected = true;
                                this.triggerDisconnected = false;
                                this.clientSocket.Close();
                                if (this.Disconnected != null)
                                {
                                    this.Disconnected(this, new DisconnectedEventArgs ());
                                }
                            }
                        }
                    }, null);

                }
            }
            catch (SocketException se)
            {
                this.disconnected = true;
                this.triggerDisconnected = false;
                if (this.Disconnected != null)
                {
                    this.Disconnected(this, new DisconnectedEventArgs());
                }
            }
        }
        /// <summary>
        /// 发送消息，异步方式
        /// </summary>
        /// <param name="message">消息内容</param>
        public void SendMessage(MemoryStream   message)
        {
            this.SendMessage(message .ToArray ());
        }
        public static int disconnectedCount = 0;
        /// <summary>
        /// 开始异步接收
        /// </summary>
        public void StartReceive()
        {
            if (this.disconnected)
            {
                return;
            }
            //注意：当接收到新消息时，要触发NewMessage事件！
            try
            {
                byte[] tmpBuffer = new byte[1024];

                this.clientSocket.BeginReceive(tmpBuffer, 0, 1024, SocketFlags.None, result =>
                {

                    try
                    {
                        //获取收到的消息的长度。
                        var receivedLength = this.clientSocket.EndReceive(result);
                        if (receivedLength == 0)
                        {
                            this.disconnected = true;
                            this.triggerDisconnected = false;
                            this.clientSocket.Close();
                            if (this.Disconnected != null)
                            {
                                disconnectedCount++;
                                this.Disconnected(this, new DisconnectedEventArgs()
                                {
                                    CommandArgument =disconnectedCount 
                                });
                            }
                        }
                        Message receivedMessage = null;

                        using (MemoryStream messageStream = new MemoryStream(tmpBuffer, 0, receivedLength))
                        {
                            receivedMessage  = messageStream.WrapMessage(this.buffer);
                        }
                        this.DispatchNewMessages(receivedMessage);
                        this.StartReceive();
                    }
                    catch (SocketException e)
                    {
                        this.disconnected = true;
                        this.clientSocket.Close();
                        this.triggerDisconnected = false;
                        if (this.Disconnected ==null )
                        {
                            Trace.WriteLine("Disconnected is Null!------------------------------------------------");
                        }
                        if (this.Disconnected != null)
                        {
                            disconnectedCount++;
                            //Trace.WriteLine("disconnected count:" + disconnectedCount);
                            this.Disconnected(this, new DisconnectedEventArgs()
                            {
                                CommandArgument = disconnectedCount
                            });
                        }
                    }

                }, tmpBuffer);

            }
            catch (SocketException ex)
            {
                this.disconnected = true;
                this.triggerDisconnected = false;
                if (this.Disconnected == null)
                {
                    Trace.WriteLine("Disconnected is Null!------------------------------------------------");
                }
                if (this.Disconnected != null)
                { 
                    disconnectedCount++;
                    this.Disconnected(this, new DisconnectedEventArgs()
                    {
                        CommandArgument = disconnectedCount
                    });
                   
                    //Trace.WriteLine("disconnected count:" + disconnectedCount);
                }
            }
        }

        #region IDisposable Members

        public void Dispose()
        {
            this.buffer = null;
            
            this.clientSocket = null;
        }

        #endregion
    }
}
